from flask import Flask, request, jsonify, render_template, send_from_directory
from pymongo import MongoClient
from bson import ObjectId
from config.config import Config
from utils.validators import DocumentValidator
from utils.data_fetchers import DataFetcher
from utils.fda_fetcher import FDADataFetcher
from backend.qa.qa_system import QASystem
from datetime import datetime
import os
import logging

# Configure logging
logging.basicConfig(level=logging.DEBUG)
logger = logging.getLogger(__name__)

app = Flask(__name__)
app.config.from_object(Config)

# MongoDB client
client = MongoClient(app.config['MONGODB_URI'])
db = client[app.config['DB_NAME']]

# Initialize components
data_fetcher = DataFetcher()
qa_system = QASystem()

# Import after app initialization to avoid circular imports
from backend.document_management.uploader import DocumentUploader
from backend.document_management.embedding_processor import EmbeddingProcessor

uploader = DocumentUploader()
embedding_processor = EmbeddingProcessor()
fda_fetcher = FDADataFetcher()

# Routes
@app.route('/')
def index():
    """Homepage"""
    return render_template('index.html')

@app.route('/upload')
def upload_page():
    """Document upload page"""
    return render_template('upload.html')

@app.route('/documents')
def documents_page():
    """Document list page"""
    return render_template('documents.html')

@app.route('/chat')
def chat_page():
    """Chat interface page"""
    return render_template('chat.html')

@app.route('/edit/<doc_id>')
def edit_page(doc_id):
    """Edit document page"""
    return render_template('edit.html', doc_id=doc_id)

@app.route('/view/<doc_id>')
def view_page(doc_id):
    """View document page"""
    return render_template('view.html', doc_id=doc_id)

@app.route('/collections')
def collections_page():
    """Collections page"""
    return render_template('collections.html')

# API Endpoints

@app.route('/api/countries', methods=['GET'])
def get_countries():
    """Get list of all countries"""
    try:
        countries = data_fetcher.get_all_countries()
        return jsonify({'status': 'success', 'countries': countries})
    except Exception as e:
        logger.error(f"Error getting countries: {str(e)}")
        return jsonify({'status': 'error', 'message': str(e)}), 500

@app.route('/api/collections/list', methods=['GET'])
def get_collections():
    """Get list of all collections"""
    try:
        collections = data_fetcher.get_collection_list()
        return jsonify({'status': 'success', 'collections': collections})
    except Exception as e:
        logger.error(f"Error getting collections: {str(e)}")
        return jsonify({'status': 'error', 'message': str(e)}), 500

@app.route('/api/collections/stats', methods=['GET'])
def get_collection_stats():
    """Get statistics for all collections from collection_info"""
    try:
        # 从 collection_info 集合获取所有collection信息
        collections = db.collection_info.find()
        stats = []
        
        for collection in collections:
            # 计算每个collection的文档数量
            doc_count = db.documents.count_documents({'collection': collection['name']})
            stats.append({
                'name': collection['name'],
                'display_name': collection.get('display_name', collection['name']),
                'description': collection.get('description', ''),
                'document_count': doc_count,
                'color': collection.get('color', 'blue')
            })
        
        return jsonify({'status': 'success', 'collections': stats})
    except Exception as e:
        logger.error(f"Error getting collection stats: {str(e)}")
        return jsonify({'status': 'error', 'message': str(e)}), 500

@app.route('/api/collections', methods=['POST'])
def create_collection():
    """Create a new collection"""
    try:
        data = request.get_json()
        name = data.get('name', '').strip()
        description = data.get('description', '').strip()
        
        if not name:
            return jsonify({'status': 'error', 'message': 'Collection name is required'}), 400
        
        # Check if collection already exists (在两个集合中都检查)
        existing_collections = db.collections.find_one({'name': name})
        existing_info = db.collection_info.find_one({'name': name})
        if existing_collections or existing_info:
            return jsonify({'status': 'error', 'message': 'Collection already exists'}), 400
        
        # Create collection data
        collection_data = {
            'name': name,
            'display_name': name,
            'description': description,
            'document_count': 0,
            'color': 'blue',  # 默认颜色
            'created_at': datetime.now()
        }
        
        # 同时插入到两个集合
        result_collections = db.collections.insert_one(collection_data.copy())
        result_info = db.collection_info.insert_one(collection_data.copy())
        
        logger.info(f"Collection created in both collections: {name}")
        
        return jsonify({
            'status': 'success',
            'message': 'Collection created successfully',
            'collection': {
                '_id': str(result_collections.inserted_id),
                'name': name,
                'display_name': name,
                'description': description
            }
        })
    except Exception as e:
        logger.error(f"Error creating collection: {str(e)}")
        return jsonify({'status': 'error', 'message': str(e)}), 500

@app.route('/api/tags', methods=['GET'])
def get_tags():
    """Get list of tags"""
    try:
        search = request.args.get('search', '')
        tags = data_fetcher.get_tag_list(search)
        return jsonify({'status': 'success', 'tags': tags})
    except Exception as e:
        logger.error(f"Error getting tags: {str(e)}")
        return jsonify({'status': 'error', 'message': str(e)}), 500

@app.route('/api/documents/upload', methods=['POST'])
def upload_document():
    """Handle document upload"""
    try:
        logger.debug("Upload request received")
        
        if 'file' not in request.files:
            logger.error("No file in request")
            return jsonify({'status': 'error', 'message': 'No file provided', 'errors': {'file': 'No file provided'}}), 400
        
        file = request.files['file']
        if file.filename == '':
            logger.error("Empty filename")
            return jsonify({'status': 'error', 'message': 'No file selected', 'errors': {'file': 'No file selected'}}), 400
        
        # Get form data
        form_data = {
            'file_name': request.form.get('file_name', '').strip(),
            'country': request.form.get('country', '').strip(),
            'document_type': request.form.get('document_type', '').strip(),
            'regulation_id': request.form.get('regulation_id', '').strip(),
            'issuing_authority': request.form.get('issuing_authority', '').strip(),
            'collection': request.form.get('collection', '').strip(),
            'status': request.form.get('status', '').strip(),
            'effective_date': request.form.get('effective_date', '').strip(),
            'version': request.form.get('version', '').strip(),
            'tags': request.form.get('tags', '').strip()
        }
        
        # Validate
        is_valid, errors = DocumentValidator.validate_all(file, form_data)
        
        if not is_valid:
            logger.error(f"Validation errors: {errors}")
            return jsonify({
                'status': 'error',
                'message': 'Validation failed',
                'errors': errors
            }), 400
        
        # Upload document
        result = uploader.upload_document(file, form_data)
        
        if result['status'] == 'success':
            logger.info(f"Document uploaded successfully: {result.get('doc_id')}")
            
            # Process embeddings
            try:
                doc_id = ObjectId(result['doc_id'])
                embedding_result = embedding_processor.process_document(doc_id)
                logger.debug(f"Embedding processing result: {embedding_result}")
            except Exception as e:
                logger.error(f"Error processing embeddings: {str(e)}")
            
            return jsonify(result), 200
        else:
            logger.error(f"Upload failed: {result.get('message')}")
            return jsonify(result), 400
            
    except Exception as e:
        logger.error(f"Unexpected error in upload: {str(e)}", exc_info=True)
        return jsonify({
            'status': 'error',
            'message': f'Server error: {str(e)}'
        }), 500

@app.route('/api/documents', methods=['GET'])
def list_documents():
    """Get list of documents with filters and pagination"""
    try:
        search = request.args.get('search', '')
        collection = request.args.get('collection', '')
        status = request.args.get('status', '')
        page = int(request.args.get('page', 1))
        limit = int(request.args.get('limit', 20))
        
        query = {}
        if search:
            query['$or'] = [
                {'file_name': {'$regex': search, '$options': 'i'}},
                {'filename': {'$regex': search, '$options': 'i'}}
            ]
        if collection:
            query['collection'] = collection
        if status:
            query['status'] = status
        
        total = db.documents.count_documents(query)
        
        skip = (page - 1) * limit
        documents = list(db.documents.find(query)
                        .sort('update_time', -1)
                        .skip(skip)
                        .limit(limit))
        
        for doc in documents:
            doc['_id'] = str(doc['_id'])
            if 'upload_time' in doc and isinstance(doc['upload_time'], datetime):
                doc['upload_time'] = doc['upload_time'].isoformat()
            if 'update_time' in doc and isinstance(doc['update_time'], datetime):
                doc['update_time'] = doc['update_time'].isoformat()
            if 'effective_date' in doc:
                if isinstance(doc['effective_date'], datetime):
                    doc['effective_date'] = doc['effective_date'].strftime('%Y/%m/%d')
        
        return jsonify({
            'status': 'success',
            'documents': documents,
            'total': total,
            'page': page,
            'limit': limit
        })
        
    except Exception as e:
        logger.error(f"Error listing documents: {str(e)}", exc_info=True)
        return jsonify({'status': 'error', 'message': str(e)}), 500

@app.route('/api/documents/<doc_id>', methods=['GET'])
def get_document(doc_id):
    """Get single document by ID"""
    try:
        document = db.documents.find_one({'_id': ObjectId(doc_id)})
        
        if not document:
            return jsonify({'status': 'error', 'message': 'Document not found'}), 404
        
        document['_id'] = str(document['_id'])
        
        if 'upload_time' in document and isinstance(document['upload_time'], datetime):
            document['upload_time'] = document['upload_time'].isoformat()
        if 'update_time' in document and isinstance(document['update_time'], datetime):
            document['update_time'] = document['update_time'].isoformat()
        if 'effective_date' in document:
            if isinstance(document['effective_date'], datetime):
                document['effective_date'] = document['effective_date'].strftime('%Y-%m-%d')
        
        return jsonify({
            'status': 'success',
            'document': document
        })
        
    except Exception as e:
        logger.error(f"Error getting document: {str(e)}", exc_info=True)
        return jsonify({'status': 'error', 'message': str(e)}), 500

@app.route('/api/documents/<doc_id>/metadata', methods=['GET'])
def get_document_metadata(doc_id):
    """Get document metadata for editing"""
    try:
        document = db.documents.find_one({'_id': ObjectId(doc_id)})
        
        if not document:
            return jsonify({'status': 'error', 'message': 'Document not found'}), 404
        
        document['_id'] = str(document['_id'])
        
        if 'upload_time' in document and isinstance(document['upload_time'], datetime):
            document['upload_time'] = document['upload_time'].isoformat()
        if 'update_time' in document and isinstance(document['update_time'], datetime):
            document['update_time'] = document['update_time'].isoformat()
        if 'effective_date' in document:
            if isinstance(document['effective_date'], datetime):
                document['effective_date'] = document['effective_date'].strftime('%Y-%m-%d')
            elif isinstance(document['effective_date'], str) and '/' in document['effective_date']:
                document['effective_date'] = document['effective_date'].replace('/', '-')
        
        return jsonify({
            'status': 'success',
            'document': document
        })
        
    except Exception as e:
        logger.error(f"Error getting document metadata: {str(e)}", exc_info=True)
        return jsonify({'status': 'error', 'message': str(e)}), 500

@app.route('/api/documents/<doc_id>', methods=['PUT'])
def update_document(doc_id):
    """Update document metadata"""
    try:
        data = request.get_json()
        
        form_data = {
            'file_name': data.get('file_name', '').strip(),
            'country': data.get('country', '').strip(),
            'document_type': data.get('document_type', '').strip(),
            'regulation_id': data.get('regulation_id', '').strip(),
            'issuing_authority': data.get('issuing_authority', '').strip(),
            'collection': data.get('collection', '').strip(),
            'status': data.get('status', '').strip(),
            'effective_date': data.get('effective_date', '').strip(),
            'version': data.get('version', '').strip(),
            'tags': data.get('tags', [])
        }
        
        effective_date = None
        if form_data['effective_date']:
            try:
                if '/' in form_data['effective_date']:
                    effective_date = datetime.strptime(form_data['effective_date'], '%Y/%m/%d')
                else:
                    effective_date = datetime.strptime(form_data['effective_date'], '%Y-%m-%d')
            except ValueError as e:
                logger.error(f"Date parsing error: {e}")
                return jsonify({'status': 'error', 'message': 'Invalid date format'}), 400
        
        update_data = {
            'file_name': form_data['file_name'],
            'country': form_data['country'],
            'document_type': form_data['document_type'],
            'regulation_id': form_data['regulation_id'],
            'issuing_authority': form_data['issuing_authority'],
            'collection': form_data['collection'],
            'status': form_data['status'],
            'version': form_data['version'],
            'tags': form_data['tags'] if isinstance(form_data['tags'], list) else [],
            'update_time': datetime.now()
        }
        
        if effective_date:
            update_data['effective_date'] = effective_date
        
        result = db.documents.update_one(
            {'_id': ObjectId(doc_id)},
            {'$set': update_data}
        )
        
        if result.modified_count > 0:
            logger.info(f"Document {doc_id} updated successfully")
            return jsonify({'status': 'success', 'message': 'Document updated successfully'})
        else:
            return jsonify({'status': 'success', 'message': 'No changes made'})
            
    except Exception as e:
        logger.error(f"Error updating document: {str(e)}", exc_info=True)
        return jsonify({'status': 'error', 'message': str(e)}), 500

@app.route('/api/documents/<doc_id>', methods=['DELETE'])
def delete_document(doc_id):
    """Delete a document"""
    try:
        document = db.documents.find_one({'_id': ObjectId(doc_id)})
        
        if not document:
            return jsonify({'status': 'error', 'message': 'Document not found'}), 404
        
        if 'file_path' in document and os.path.exists(document['file_path']):
            os.remove(document['file_path'])
        
        db.documents.delete_one({'_id': ObjectId(doc_id)})
        db.document_chunks.delete_many({'document_id': ObjectId(doc_id)})
        
        logger.info(f"Document {doc_id} deleted successfully")
        return jsonify({'status': 'success', 'message': 'Document deleted successfully'})
        
    except Exception as e:
        logger.error(f"Error deleting document: {str(e)}", exc_info=True)
        return jsonify({'status': 'error', 'message': str(e)}), 500

@app.route('/fda-analysis')
def fda_analysis_page():
    """FDA data analysis page"""
    return render_template('fda_analysis.html')

# FDA API Endpoints
@app.route('/api/fda/510k', methods=['POST'])
def get_fda_510k():
    """Get 510(k) records from FDA for a single product code"""
    try:
        data = request.get_json()
        product_code = data.get('product_code', '')
        limit = data.get('limit', 10)
        
        if not product_code:
            return jsonify({'status': 'error', 'message': 'Product code is required'}), 400
        
        result = fda_fetcher.get_510k_records(product_code, limit)
        return jsonify(result)
        
    except Exception as e:
        logger.error(f"Error fetching 510(k) data: {str(e)}")
        return jsonify({'status': 'error', 'message': str(e)}), 500

@app.route('/api/fda/adverse-events', methods=['POST'])
def get_fda_adverse_events():
    """Get adverse event statistics from FDA for a single product code"""
    try:
        data = request.get_json()
        product_code = data.get('product_code', '')
        
        if not product_code:
            return jsonify({'status': 'error', 'message': 'Product code is required'}), 400
        
        result = fda_fetcher.get_adverse_events_stats(product_code)
        return jsonify(result)
        
    except Exception as e:
        logger.error(f"Error fetching adverse event data: {str(e)}")
        return jsonify({'status': 'error', 'message': str(e)}), 500

@app.route('/api/fda/recalls', methods=['POST'])
def get_fda_recalls():
    """Get recall statistics from FDA for a single product code"""
    try:
        data = request.get_json()
        product_code = data.get('product_code', '')
        
        if not product_code:
            return jsonify({'status': 'error', 'message': 'Product code is required'}), 400
        
        result = fda_fetcher.get_recall_stats(product_code)
        return jsonify(result)
        
    except Exception as e:
        logger.error(f"Error fetching recall data: {str(e)}")
        return jsonify({'status': 'error', 'message': str(e)}), 500

@app.route('/api/fda/compare', methods=['POST'])
def get_fda_comparison():
    """Compare two product codes"""
    try:
        data = request.get_json()
        product_codes = data.get('product_codes', [])
        
        if len(product_codes) != 2:
            return jsonify({'status': 'error', 'message': 'Exactly two product codes required'}), 400
        
        result = fda_fetcher.compare_products(product_codes)
        return jsonify(result)
        
    except Exception as e:
        logger.error(f"Error fetching comparison data: {str(e)}")
        return jsonify({'status': 'error', 'message': str(e)}), 500

# 新增端点：获取可用产品代码列表
@app.route('/api/fda/product-codes', methods=['GET'])
def get_fda_product_codes():
    """Get list of available product codes"""
    try:
        # 从配置中获取默认代码
        default_codes = app.config.get('FDA_DEFAULT_PRODUCT_CODES', ['OHV', 'GEX', 'GEI', 'ONG', 'QAI', 'NGX', 'PBX'])
        
        # 也可以从数据库或缓存中获取其他代码
        return jsonify({
            'status': 'success',
            'product_codes': default_codes,
            'total': len(default_codes)
        })
        
    except Exception as e:
        logger.error(f"Error getting product codes: {str(e)}")
        return jsonify({'status': 'error', 'message': str(e)}), 500

@app.route('/api/chat/ask', methods=['POST'])
def chat_ask():
    """Handle chat questions with DeepSeek integration"""
    try:
        data = request.get_json()
        question = data.get('question', '').strip()
        session_id = data.get('session_id')
        collection_filter = data.get('collection_filter')
        
        if not question:
            return jsonify({'status': 'error', 'message': 'Question is required'}), 400
        
        logger.debug(f"Chat question: {question}, Collection filter: {collection_filter}")
        
        # Use QA system to get answer
        result = qa_system.ask_question(
            question=question,
            session_id=session_id,
            collection_filter=collection_filter
        )
        
        return jsonify({
            'status': 'success',
            'result': result
        })
        
    except Exception as e:
        logger.error(f"Error in chat: {str(e)}", exc_info=True)
        return jsonify({'status': 'error', 'message': str(e)}), 500

@app.teardown_appcontext
def cleanup(error=None):
    """Cleanup resources"""
    if hasattr(fda_fetcher, 'close'):
        fda_fetcher.close()

@app.route('/api/fda/debug', methods=['GET'])
def debug_fda_api():
    """Debug FDA API connection"""
    try:
        # 创建新的fetcher实例
        debug_fetcher = FDADataFetcher(
            api_key=app.config.get('FDA_API_KEY'),
            base_url="https://api.fda.gov"
        )
        
        # 测试连接
        test_results = debug_fetcher.test_connection()
        
        # 测试具体产品代码
        test_codes = ['OHV', 'GEX', 'GEI', 'PBX']
        product_results = []
        
        for code in test_codes:
            try:
                # 测试510(k)
                k_data = debug_fetcher.get_510k_records(code, limit=1)
                product_results.append({
                    'code': code,
                    '510k_success': k_data.get('status') == 'success',
                    '510k_total': k_data.get('total', 0),
                    '510k_records': len(k_data.get('records', []))
                })
            except Exception as e:
                product_results.append({
                    'code': code,
                    'error': str(e)
                })
        
        debug_fetcher.close()
        
        return jsonify({
            'status': 'success',
            'api_key_configured': bool(app.config.get('FDA_API_KEY')),
            'api_key_length': len(app.config.get('FDA_API_KEY', '')),
            'test_results': test_results,
            'product_tests': product_results,
            'config_keys': {
                'FDA_API_KEY': 'SET' if app.config.get('FDA_API_KEY') else 'NOT SET',
                'FDA_BASE_URL': app.config.get('FDA_BASE_URL', 'NOT SET')
            }
        })
        
    except Exception as e:
        logger.error(f"Debug error: {str(e)}", exc_info=True)
        return jsonify({'error': str(e)}), 500

# 添加一个简单的测试端点
@app.route('/api/fda/test-simple', methods=['GET'])
def test_fda_simple():
    """Simple test of FDA API without complex queries"""
    try:
        # 直接测试API
        import requests
        
        # 使用一个已知有效的查询
        params = {
            'search': 'product_code:"GEI"',
            'limit': 2
        }
        
        if app.config.get('FDA_API_KEY'):
            params['api_key'] = app.config.get('FDA_API_KEY')
        
        response = requests.get(
            "https://api.fda.gov/device/510k.json",
            params=params,
            timeout=10
        )
        
        return jsonify({
            'status_code': response.status_code,
            'url': response.url,
            'params': params,
            'response_keys': list(response.json().keys()) if response.status_code == 200 else [],
            'sample_data': response.json().get('results', [])[:1] if response.status_code == 200 else []
        })
        
    except Exception as e:
        return jsonify({'error': str(e)}), 500        

if __name__ == '__main__':
    app.run(debug=True, host='0.0.0.0', port=5000)